home *** CD-ROM | disk | FTP | other *** search
- #include <conio.h>
- #include <math.h>
- #include <stdlib.h>
- #include <time.h>
- #include <dos.h>
- #include <wgt5.h>
- #include <wgtvesa.h>
-
- /* WGT 3D Rendering Library
- Copyright 1995 Egerter Software */
-
- /* Triangle Rendering Methods */
- #define WIREFRAME 0
- #define SOLID 1
- #define GOURAUD 2
- #define TEXTURE 3
- #define FLAT_SHADED_TEXTURE 4
- #define GOURAUD_SHADED_TEXTURE 5
- #define TRANSLUCENT_TEXTURE 6
- #define TRANSLUCENT_GOURAUD 7
-
- #define M_PI 3.1415926535897932384626
-
- #define POLYBUF 10000 /* Maximum polys per frame */
- #define OBJBUF 100 /* Maximum objects in world */
- #define MAXKEYS 100 /* Maximum animation keys per object */
- #define MAXCHILDREN 10 /* Maximum child objects per parent */
- #define MAX_TEXTURES 10 /* Maximum textures loaded at once */
-
- float render_shades = 64; /* Number of colors reserved for shading a
- single color */
- int render_all = 0; /* 0 = backface removal */
-
-
- /* Our 3D system structures */
- typedef struct
- {
- float x, y, z;
- } point3d; /* A single 3D point */
-
-
- typedef struct
- {
- point3d local;
- point3d world;
- point3d normal;
- int screenx, screeny;
- unsigned char connected;
- unsigned char rotated;
- } vertex; /* A vertex of a polygon */
-
-
- typedef struct
- {
- int vertex1;
- int vertex2;
- int vertex3;
- int type;
- point3d normal;
- point3d center;
- short status;
- unsigned char color;
- } triangle_3d; /* A 3D triangle */
-
-
- typedef struct
- {
- float sx, sy, sz; /* Scale */
- float tx, ty, tz; /* Translation */
- float rx, ry, rz; /* Rotation */
- int framenumber;
- char update_scale;
- char update_rotation;
- char update_translation;
- } keydata; /* Key animation data */
-
-
- typedef struct
- {
- int start_poly;
- int end_poly;
- int startpoints;
- int points;
-
- float minx;
- float maxx;
- float miny;
- float maxy;
- float minz;
- float maxz;
-
- /* Added for animation */
- float translatex;
- float translatey; /* Added to each vertex each frame */
- float translatez;
-
- float pivotx;
- float pivoty; /* Pivot location for this object */
- float pivotz;
-
- float scalex;
- float scaley; /* Multiplied by each vertex based on the distance */
- float scalez; /* from the pivot location */
-
- float rotatex;
- float rotatey; /* Each vertex is rotated by this amount */
- float rotatez;
-
- /* Hierarchy */
- short int level;
- short maxchild; /* Number of children */
- unsigned short int children[MAXCHILDREN];
- short parent; /* Parent of this object */
-
- keydata keylist[MAXKEYS]; /* Array of key frames */
- int maxframe; /* Max animation frame */
- int currentframe; /* Current animation frame */
-
- int tstepsleft; /* Translation steps left */
- int rstepsleft; /* Rotation steps left */
-
- char name[15]; /* Name of object */
- } object_3d;
-
-
- struct {
- float lens;
- float fov;
- } cameras[9] = { 15, 115, 20, 94.28571, 24, 84, 28, 76.36, 35, 63,
- 50, 46, 85, 28, 135, 18, 200, 12 };
-
- /* For shaded texture mapping */
- unsigned char *render_shadetable;
-
- tpoint renderpoly[3]; /* Used to draw one triangle at a time */
-
- typedef struct {
- int number; /* Sorted polygon # */
- float depth; /* Center depth of polygon */
- } sort;
-
- sort sorted_polys[POLYBUF];
-
-
- typedef struct
- {
- long sx[3];
- long sy[3];
- } polytexture;
-
- polytexture ptext[POLYBUF]; /* Holds texture coordinates for each
- triangle in the polylist */
-
- point3d camera; /* Camera position */
- point3d camera_norm; /* Camera position */
- point3d focus; /* Target position */
- point3d tvect; /* Eye vector */
-
- struct {
- point3d world;
- point3d normal;
- } light; /* Light position */
-
- float fov; /* Field of view in degrees */
- float dist; /* Distance from viewer */
- float m11, m12, m21, m22, m23, m31, m32, m33;
-
- triangle_3d polylist[POLYBUF]; /* Polygon list for world */
- object_3d objectlist[OBJBUF]; /* Object list for world */
-
- block textures[MAX_TEXTURES];
-
- float camera_x, camera_y, camera_z;
- float focus_x, focus_y, focus_z;
- float light_x, light_y, light_z;
- float camera_angle;
- int worldpoints;
- int totalpoly = 0;
- int totalobjects = 0;
-
-
- /* The following are defined in wrendani.c, used for moving, scaling, and
- rotating objects. */
-
- extern void translate_object (object_3d *obj, vertex *pts, float x, float y,
- float z);
- /* Adds x,y,z to each 3D point in the object */
-
-
- extern void scale_object (object_3d *obj, vertex *pts,
- float x, float y, float z,
- float px, float py, float pz);
- /* Scales by x,y,z, based on the distance from px,py,pz */
-
-
- extern void rotate_object (object_3d *obj, vertex *pts,
- float x, float y, float z,
- float px, float py, float pz);
- /* Rotates the object by x,y,z around the center point px,py,pz */
-
-
- extern void set_object_pivot (object_3d *obj, float x, float y, float z);
- /* Sets x,y,z as the center of the object */
-
-
- extern void rotate_point (float *ptx, float *pty, float *ptz,
- float x, float y, float z,
- float px, float py, float pz);
- /* Rotates a single point by x,y,z around px,py,pz */
-
-
- /* The following are defined in this file: */
-
- void map_plane (float x, float y, float z, long *u, long *v, float scale);
- /* Given a 3D point, maps the point onto the x/y plane */
-
- float dot_product (point3d *a, point3d *b);
- /* Compute the dot product between two 3D vectors */
-
- void wset_focus (float a, float b, float c);
- /* Sets where the camera is looking at */
-
- void wset_camera (float a, float b, float c);
- /* Sets the position of the camera */
-
- void wset_light (float a, float b, float c);
- /* Sets the position of the light */
-
- void wset_view (void);
- /* Sets up the viewing matrix based on the camera position and direction */
-
- void wworld_2_view (object_3d *obj, int *drawtotal, vertex *vlist);
- /* Transform the 3D coordinates to 2D coordinates */
-
- void calc_normal (vertex *wp1, vertex *wp2, vertex *wp3, point3d *norm);
- /* Calculates a normal vector given three vertices */
-
- void map_points (short obj, vertex *pts, float scale);
- /* Map all the texture coordinates onto a plane, given an object and a scale */
-
- int sortkeys (keydata *a, keydata *b);
- /* Sorts the animation keys by their frame number */
-
- void adjust_object (object_3d *objp, float rx, float ry, float rz,
- float px, float py, float pz);
- /* Modify an object's animation data if it has a parent */
-
- void duplicate_frame (object_3d *obj, int frame, int framenumber);
- /* Copies one animation key to another */
-
- void build_hierarchy (void);
- /* Connects children and parents together */
-
- void add_key_translate (object_3d *obj, int framenumber, float x, float y,
- float z);
- /* Adds a translation animation key */
-
- void add_key_scale (object_3d *obj, int framenumber, float x, float y,
- float z);
- /* Adds a scale animation key */
-
- void add_key_rotate (object_3d *obj, int framenumber, float x, float y,
- float z);
- /* Adds a rotation animation key */
-
- int find_object (char *name);
- /* Given the name of an object, returns the index in objectlist */
-
- void add_child (int parent, int child);
- /* Adds a child to a parent object */
-
- void load_3ds (char *filename, vertex *pts);
- /* Loads a 3D Studio file */
-
- int compare (sort *a, sort *b);
- /* Used for sorting */
-
- void draw_polys (vertex *pts, int drawtotal);
- /* Draws the polygons */
-
- void wset_object_color (int obj, unsigned char col);
- /* Sets the color of each triangle in an object, used for solid, gouraud, and
- texture. For textured objects, the color represents the texture number
- from the textures array. */
-
- void wset_object_type (int obj, int type);
- /* Sets the rendering method for an object */
-
- void wreset_3d_system (void);
- /* Resets the engine so you can load in a new object */
-
- /***************************************************************************/
- float dot_product (point3d *a, point3d *b)
- /* Compute the dot product between two 3D vectors */
- {
- return ( (a->x * b->x) + (a->y * b->y) + (a->z * b->z) );
- }
-
-
- void wset_focus (float a, float b, float c)
- /* Sets where the camera is looking at */
- {
- focus.x = a;
- focus.y = b;
- focus.z = c;
- }
-
-
- void wset_camera (float a, float b, float c)
- /* Sets the position of the camera */
- {
- float norm;
-
- camera.x = a;
- camera.y = b;
- camera.z = c;
- norm = sqrt( (a * a) + (b * b) + (c * c) );
- camera_norm.x = a / norm;
- camera_norm.y = b / norm;
- camera_norm.z = c / norm;
- }
-
-
- void wset_light (float a, float b, float c)
- /* Sets the position of the light */
- {
- float norm;
-
- light.world.x = a;
- light.world.y = b;
- light.world.z = c;
- norm = sqrt( (a * a) + (b * b) + (c * c) );
- light.normal.x = a / norm;
- light.normal.y = b / norm;
- light.normal.z = c / norm;
- }
-
-
- void wset_view (void)
- /* Sets up the viewing matrix based on the camera position and direction */
- {
- float lambda;
- float tlength;
-
- lambda = ((fov / 180.0) * 3.1415);
- dist = 100.0 / sin(lambda / 2);
-
- tvect.x = focus.x - camera.x;
- tvect.y = focus.y - camera.y;
- tvect.z = focus.z - camera.z;
- lambda = sqrt ( (tvect.x * tvect.x) + (tvect.y * tvect.y) );
- tlength = sqrt ( (tvect.x * tvect.x) + (tvect.y * tvect.y) + (tvect.z * tvect.z) );
-
- m11 = tvect.y / lambda;
- m12 = -tvect.x / lambda;
- m21 = (tvect.x * tvect.z) / (lambda * tlength);
- m22 = (tvect.y * tvect.z) / (lambda * tlength);
- m23 = -lambda / tlength;
- m31 = tvect.x / tlength;
- m32 = tvect.y / tlength;
- m33 = tvect.z / tlength;
- }
-
-
- void wworld_2_view (object_3d *obj, int *drawtotal, vertex *vlist)
- /* Transform the 3D coordinates to 2D coordinates */
- {
- int poly, start, finish;
- float xo, yo, zo;
- float xo2, yo2, zo2;
- float xo3, yo3, zo3;
- float min_depth, max_depth, temp;
- triangle_3d *ptr;
- point3d lineofsite;
- vertex *vptr;
- vertex *vptr2;
- vertex *vptr3;
- float xres, yres;
-
- xres = (float)WGT_SYS.xres / 2.0;
- yres = (float)WGT_SYS.yres / 2.0;
- start = obj->start_poly;
- finish = obj->end_poly;
-
- for (poly = start; poly <= finish; poly++)
- {
- ptr = &polylist[poly];
- vptr = &vlist[ptr->vertex1];
- vptr2 = &vlist[ptr->vertex2];
- vptr3 = &vlist[ptr->vertex3];
-
- lineofsite.x = vptr->local.x - camera.x;
- lineofsite.y = vptr->local.y - camera.y;
- lineofsite.z = vptr->local.z - camera.z;
- if ((dot_product (&lineofsite, &ptr->normal) >= 0) || (render_all))
- {
- if (vptr->rotated == 0)
- {
- xo = vptr->local.x - camera.x;
- yo = vptr->local.y - camera.y;
- zo = vptr->local.z - camera.z;
-
- vptr->world.z = (xo * m31) + (yo * m32) + (zo * m33);
- }
- if (vptr2->rotated == 0)
- {
- xo2 = vptr2->local.x - camera.x;
- yo2 = vptr2->local.y - camera.y;
- zo2 = vptr2->local.z - camera.z;
-
- vptr2->world.z = (xo2 * m31) + (yo2 * m32) + (zo2 * m33);
- }
- if (vptr3->rotated == 0)
- {
- xo3 = vptr3->local.x - camera.x;
- yo3 = vptr3->local.y - camera.y;
- zo3 = vptr3->local.z - camera.z;
-
- vptr3->world.z = (xo3 * m31) + (yo3 * m32) + (zo3 * m33);
- }
- if ( (vptr->world.z > 0) || (vptr2->world.z > 0) || (vptr3->world.z > 0))
- {
- if (vptr->rotated == 0)
- {
- vptr->world.x = (xo * m11) + (yo * m12);
- vptr->world.y = (xo * m21) + (yo * m22) + (zo * m23);
- /* PROJECTION */
- temp = dist / vptr->world.z;
- vptr->screenx = (vptr->world.x * temp) + xres;
- vptr->screeny = (vptr->world.y * temp) + yres;
- vptr->rotated = 1;
- }
- if (vptr2->rotated == 0)
- {
- vptr2->world.x = (xo2 * m11) + (yo2 * m12);
- vptr2->world.y = (xo2 * m21) + (yo2 * m22) + (zo2 * m23);
- /* PROJECTION */
- temp = dist / vptr2->world.z;
- vptr2->screenx = (vptr2->world.x * temp) + xres;
- vptr2->screeny = (vptr2->world.y * temp) + yres;
- vptr2->rotated = 1;
- }
- if (vptr3->rotated == 0)
- {
- vptr3->world.x = (xo3 * m11) + (yo3 * m12);
- vptr3->world.y = (xo3 * m21) + (yo3 * m22) + (zo3 * m23);
- /* PROJECTION */
- temp = dist / vptr3->world.z;
- vptr3->screenx = (vptr3->world.x * temp) + xres;
- vptr3->screeny = (vptr3->world.y * temp) + yres;
- vptr3->rotated = 1;
- }
- if ( ((vptr->screenx >= 0) || (vptr2->screenx >= 0) || (vptr3->screenx >= 0))
- && ((vptr->world.z > 1) && (vptr2->world.z > 1) && (vptr3->world.z > 1))
- && ((vptr->screeny >= 0) || (vptr2->screeny >= 0) || (vptr3->screeny >= 0))
- && ((vptr->screenx < WGT_SYS.xres) || (vptr2->screenx < WGT_SYS.xres) || (vptr3->screenx < WGT_SYS.xres))
- && ((vptr->screeny < WGT_SYS.yres) || (vptr2->screeny < WGT_SYS.yres) || (vptr3->screeny < WGT_SYS.yres)) )
- {
- sorted_polys[*drawtotal].number = poly;
- /* Rotate center of polygon */
-
- /* Center of polygon, Z sorting */
- /* xo = ptr->center.x - camera.x;
- yo = ptr->center.y - camera.y;
- zo = ptr->center.z - camera.z;
- sorted_polys[*drawtotal].depth = (xo * m31) + (yo * m32) + (zo * m33); */
-
- /* Farthest Z Sorting */
- /* zo = vptr->world.z;
- if (vptr2->world.z > zo)
- zo = vptr2->world.z;
- if (vptr3->world.z > zo)
- zo = vptr3->world.z;
- sorted_polys[*drawtotal].depth = zo;*/
-
- /* Average Z Sorting */
- sorted_polys[*drawtotal].depth = (vptr->world.z + vptr2->world.z +
- vptr3->world.z) / 3.0;
-
- *drawtotal = *drawtotal + 1;
- }
- }
- }
- }
- }
-
-
- void calc_normal (vertex *wp1, vertex *wp2, vertex *wp3, point3d *norm)
- /* Calculates a normal vector given three vertices */
- {
- point3d a, b;
-
- a.x = wp2->local.x - wp1->local.x;
- a.y = wp2->local.y - wp1->local.y;
- a.z = wp2->local.z - wp1->local.z;
-
- b.x = wp3->local.x - wp1->local.x;
- b.y = wp3->local.y - wp1->local.y;
- b.z = wp3->local.z - wp1->local.z;
-
- norm->x = (a.y * b.z) - (a.z * b.y);
- norm->y = (a.z * b.x) - (a.x * b.z);
- norm->z = (a.x * b.y) - (a.y * b.x);
-
- /* Normalize it */
- a.x = sqrt((norm->x * norm->x) + (norm->y * norm->y) + (norm->z * norm->z));
- norm->x /= a.x;
- norm->y /= a.x;
- norm->z /= a.x;
- }
-
-
-
-
-
- void map_points (int obj, vertex *pts, float scale)
- /* Map all the texture coordinates onto a plane, given an object and a scale */
- {
- int ply;
- int vert;
- triangle_3d *polyptr;
-
-
- for (ply = objectlist[obj].start_poly; ply <= objectlist[obj].end_poly; ply++)
- {
- polyptr = &polylist[ply];
- map_plane (pts[polyptr->vertex1].local.x, pts[polyptr->vertex1].local.y,
- pts[polyptr->vertex1].local.z, &ptext[ply].sx[0],
- &ptext[ply].sy[0], scale);
- map_plane (pts[polyptr->vertex2].local.x, pts[polyptr->vertex2].local.y,
- pts[polyptr->vertex2].local.z, &ptext[ply].sx[1],
- &ptext[ply].sy[1], scale);
- map_plane (pts[polyptr->vertex3].local.x, pts[polyptr->vertex3].local.y,
- pts[polyptr->vertex3].local.z, &ptext[ply].sx[2],
- &ptext[ply].sy[2], scale);
- }
- }
-
-
-
- int sortkeys (keydata *a, keydata *b)
- /* Sorts the animation keys by their frame number */
- {
- if (a->framenumber < b->framenumber)
- return -1;
- else if (a->framenumber > b->framenumber)
- return 1;
- else return 0;
- }
-
-
-
-
- void adjust_object (object_3d *objp, float rx, float ry, float rz,
- float px, float py, float pz)
- /* Modify an object's animation data if it has a parent */
- {
- int child;
- int frame;
- object_3d *objc;
- keydata *key;
-
-
- if (objp->maxchild > -1)
- {
- for (child = 0; child <= objp->maxchild; child++)
- {
- objc = &objectlist[objp->children[child]];
- rotate_point (&objc->pivotx, &objc->pivoty, &objc->pivotz,
- -rx, -ry, -rz, 0, 0, 0);
- rotate_point (&objc->pivotx, &objc->pivoty, &objc->pivotz,
- objc->keylist[0].rx, objc->keylist[0].ry, objc->keylist[0].rz,
- 0, 0, 0);
- objc->pivotx += px;
- objc->pivoty += py;
- objc->pivotz += pz;
-
- if (objc->maxframe > -1)
- for (frame = 1; frame <= objc->maxframe; frame++)
- {
- key = &objc->keylist[frame];
- rotate_point (&key->rx, &key->ry, &key->rz, -rx, -ry, -rz, 0, 0, 0);
- // rotate_point (&key->rx, &key->rx, &key->rx,
- //objc->keylist[0].rx, objc->keylist[0].ry, objc->keylist[0].rz,
- //0, 0, 0);
-
- rotate_point (&key->tx, &key->ty, &key->tz, rx, ry, rz, 0, 0, 0);
- }
-
-
-
- adjust_object (objc, rx, ry, rz, px, py, pz);
- }
- }
- }
-
-
- void duplicate_frame (object_3d *obj, int frame, int framenumber)
- /* Copies one animation key to another */
- {
- int lastkey;
-
- lastkey = obj->maxframe+1;
- memcpy (&obj->keylist[lastkey], &obj->keylist[frame], sizeof (keydata));
- obj->keylist[lastkey].framenumber = framenumber;
- obj->maxframe++;
- obj->keylist[lastkey].rx = 0;
- obj->keylist[lastkey].ry = 0;
- obj->keylist[lastkey].rz = 0;
- obj->keylist[lastkey].update_rotation = 1;
- obj->keylist[lastkey].update_translation = 0;
- }
-
-
-
- #include <stddef.h>
-
- void qsort (void *base,
- size_t nel,
- size_t width,
- int (*comp)(const void *, const void *))
- {
- size_t wnel, gap, wgap, i, j, k;
- char *a, *b, tmp;
-
- wnel = width * nel;
- for (gap = 0; ++gap < nel;)
- gap *= 3;
- while ( gap /= 3 )
- {
- wgap = width * gap;
- for (i = wgap; i < wnel; i += width)
- {
- for (j = i - wgap; ;j -= wgap)
- {
- a = j + (char *)base;
- b = a + wgap;
- if ( (*comp)(a, b) <= 0 )
- break;
- k = width;
- do
- {
- tmp = *a;
- *a++ = *b;
- *b++ = tmp;
- } while ( --k );
- if (j < wgap)
- break;
- }
- }
- }
- }
-
-
- void build_hierarchy (void)
- /* Connects children and parents together */
- {
- object_3d *objp;
- object_3d *objc;
-
- int obj, obj2;
- int level;
- float rx, ry, rz;
- float crx, cry, crz;
-
- int lastframe, testframe;
-
-
- lastframe = 0;
- /* Sort keyframes */
- for (obj = 0; obj < totalobjects; obj++)
- {
- objp = &objectlist[obj];
- qsort (objp->keylist, objp->maxframe+1, sizeof (keydata), sortkeys);
-
- testframe = objp->keylist[objp->maxframe].framenumber;
- if (testframe > lastframe)
- lastframe = testframe;
- }
-
- for (obj = 0; obj < totalobjects; obj++)
- {
- objp = &objectlist[obj];
- objp->pivotx = objp->keylist[0].tx;
- objp->pivoty = objp->keylist[0].ty;
- objp->pivotz = objp->keylist[0].tz;
-
- testframe = objp->keylist[objp->maxframe].framenumber;
- if ((testframe != lastframe) && (objp->maxframe > 0))
- duplicate_frame (objp, objp->maxframe, lastframe);
- }
-
-
- for (obj = 0; obj < totalobjects; obj++)
- {
- objp = &objectlist[obj];
-
- rx = objp->keylist[0].rx;
- ry = objp->keylist[0].ry;
- rz = objp->keylist[0].rz;
-
- crx = objp->pivotx;
- cry = objp->pivoty;
- crz = objp->pivotz;
-
- adjust_object (objp, rx, ry, rz, crx, cry, crz);
- }
- }
-
-
- void add_key_translate (object_3d *obj, int framenumber, float x, float y, float z)
- /* Adds a translation animation key */
- {
- int key;
- int foundkey;
-
- foundkey = -1;
- for (key = 0; key <= obj->maxframe; key++)
- if (obj->keylist[key].framenumber == framenumber)
- foundkey = key;
-
- if (foundkey == -1)
- {
- obj->maxframe++;
- foundkey = obj->maxframe;
- obj->keylist[foundkey].framenumber = framenumber;
- }
-
- obj->keylist[foundkey].tx = x;
- obj->keylist[foundkey].ty = y;
- obj->keylist[foundkey].tz = z;
- obj->keylist[foundkey].update_translation = 1;
-
- }
-
-
- void add_key_scale (object_3d *obj, int framenumber, float x, float y, float z)
- /* Adds a scale animation key */
- {
- int key;
- int foundkey;
-
- foundkey = -1;
- for (key = 0; key <= obj->maxframe; key++)
- if (obj->keylist[key].framenumber == framenumber)
- foundkey = key;
-
- if (foundkey == -1)
- {
- obj->maxframe++;
- foundkey = obj->maxframe;
- obj->keylist[foundkey].framenumber = framenumber;
- }
-
- obj->keylist[foundkey].sx = x;
- obj->keylist[foundkey].sy = y;
- obj->keylist[foundkey].sz = z;
- obj->keylist[foundkey].update_scale = 1;
- }
-
-
- void add_key_rotate (object_3d *obj, int framenumber, float x, float y, float z)
- /* Adds a rotation animation key */
- {
- int key;
- int foundkey;
-
- foundkey = -1;
- for (key = 0; key <= obj->maxframe; key++)
- if (obj->keylist[key].framenumber == framenumber)
- foundkey = key;
-
- if (foundkey == -1)
- {
- obj->maxframe++;
- foundkey = obj->maxframe;
- obj->keylist[foundkey].framenumber = framenumber;
- }
-
- obj->keylist[foundkey].rx = x;
- obj->keylist[foundkey].ry = y;
- obj->keylist[foundkey].rz = z;
- obj->keylist[foundkey].update_rotation = 1;
- }
-
-
- int find_object (char *name)
- /* Given the name of an object, returns the index in objectlist */
- {
- int obj;
- int found;
-
- found = -1;
- for (obj = 0; obj < totalobjects; obj++)
- {
- if (strcmp (objectlist[obj].name, name) == 0)
- found = obj;
- }
-
- return (found);
- }
-
-
-
- void add_child (int parent, int child)
- /* Adds a child to a parent object */
- {
- objectlist[child].parent = parent;
- objectlist[parent].maxchild++;
- objectlist[parent].children[objectlist[parent].maxchild] = child;
- }
-
-
-
- void load_3ds (char *filename, vertex *pts)
- /* Loads a 3D Studio file */
- {
- FILE *in;
- float camx, camy, camz;
- float tarx, tary, tarz;
- float lightx, lighty, lightz;
- float mat11, mat12, mat13, mat21, mat22, mat23, mat31, mat32, mat33,
- mat41, mat42, mat43;
- float lens;
- float bank;
- float min_depth, max_depth;
- float x, y, z;
- unsigned short int p1, p2, p3, p4;
- char c;
- char objname[20];
- unsigned int nextobj;
- unsigned short vertices;
- unsigned short polys;
- int vertcnt;
- vertex *vptr, *vptr2, *vptr3;
- char buffer[120];
- int i, ctr;
- int hiernum;
- int prevobj;
-
- long filelen;
-
- int numkeys;
- short framenumber;
- float rx, ry, rz;
- float rangle;
-
- short level;
-
- struct {
- unsigned short chunk_id;
- unsigned int next_chunk;
- } chunk;
-
-
- hiernum = -1;
-
-
- vertcnt = 0;
- totalobjects = 0;
- totalpoly = 0;
-
- /* Library code */
- if (wgtlibrary == NULL)
- {
- if ((libf = fopen (filename, "rb")) == NULL)
- goto l3dsstop;
- }
- else
- {
- if ((libf = fopen (wgtlibrary, "rb")) == NULL)
- goto l3dsstop;
- readheader ();
- findfile (filename);
- if (lresult == 1)
- fseek (libf, lfpos, SEEK_SET);
- if (checkpassword (password) == 0)
- {
- wsetmode (3);
- printf ("Incorrect password");
- exit (1);
- }
- }
-
- if ((wgtlibrary != NULL) & (lresult == 0)) goto l3dsstop;
- /* Library code */
- in = libf;
-
- filelen = filelength (fileno(in));
- fread (&chunk, 6, 1, in);
- if (chunk.chunk_id == 0x4d4d)
- while (!feof (in) && (ftell(in) < filelen))
- {
- fread (&chunk, 6, 1, in);
- switch (chunk.chunk_id) {
- case 0x3d3d : // Loading mesh
- break;
- case 0x4000 : // Found object
- nextobj = ftell (in) + chunk.next_chunk - 6;
- objectlist[totalobjects].points = 0;
- objectlist[totalobjects].maxchild = -1;
- c = 0;
-
- /* Read the object name */
- do {
- objname[c] = fgetc (in);
- c++;
- } while (objname[c-1] != 0);
- strcpy (objectlist[totalobjects].name, objname);
- break;
- case 0x4100 : // Triangular polygon object
- break;
- case 0x4110 : // Loading vertices
- fread (&vertices, 2, 1, in);
- objectlist[totalobjects].points = vertices;
- objectlist[totalobjects].startpoints = vertcnt;
- for (i = 0; i < vertices; i++)
- {
- fread (&x, 4, 1, in);
- fread (&y, 4, 1, in);
- fread (&z, 4, 1, in);
- pts[vertcnt].local.x = x;
- pts[vertcnt].local.y = y;
- pts[vertcnt].local.z = z;
- pts[vertcnt].normal.x = 0;
- pts[vertcnt].normal.y = 0;
- pts[vertcnt].normal.z = 0;
- pts[vertcnt].rotated = 0;
- pts[vertcnt].connected = 0;
- vertcnt++;
- }
- break;
- case 0x4120 : // Loading polygons
- fread (&polys, 2, 1, in);
- objectlist[totalobjects].maxframe = -1;
- objectlist[totalobjects].maxchild = -1;
-
- objectlist[totalobjects].currentframe = 0;
- objectlist[totalobjects].tstepsleft = -1;
- objectlist[totalobjects].rstepsleft = -1;
-
- objectlist[totalobjects].scalex = 1;
- objectlist[totalobjects].scaley = 1;
- objectlist[totalobjects].scalez = 1;
-
- objectlist[totalobjects].translatex = 0;
- objectlist[totalobjects].translatey = 0;
- objectlist[totalobjects].translatez = 0;
-
- objectlist[totalobjects].start_poly = totalpoly;
- for (i = 0; i < polys; i++)
- {
- fread (&p1, 2, 1, in);
- fread (&p2, 2, 1, in);
- fread (&p3, 2, 1, in);
- fread (&p4, 2, 1, in);
- ctr = vertcnt - vertices;
- p1 += ctr;
- p2 += ctr;
- p3 += ctr;
-
- polylist[totalpoly].vertex1 = p1;
- polylist[totalpoly].vertex2 = p2;
- polylist[totalpoly].vertex3 = p3;
- polylist[totalpoly].type = 1;
- polylist[totalpoly].status = p4;
- polylist[totalpoly].color = 0;
- vptr = &pts[polylist[totalpoly].vertex1];
- vptr2 = &pts[polylist[totalpoly].vertex2];
- vptr3 = &pts[polylist[totalpoly].vertex3];
- calc_normal (&pts[p3], &pts[p2], &pts[p1],
- &polylist[totalpoly].normal);
- vptr->normal.x += polylist[totalpoly].normal.x;
- vptr->normal.y += polylist[totalpoly].normal.y;
- vptr->normal.z += polylist[totalpoly].normal.z;
- vptr->connected++;
- vptr2->normal.x += polylist[totalpoly].normal.x;
- vptr2->normal.y += polylist[totalpoly].normal.y;
- vptr2->normal.z += polylist[totalpoly].normal.z;
- vptr2->connected++;
- vptr3->normal.x += polylist[totalpoly].normal.x;
- vptr3->normal.y += polylist[totalpoly].normal.y;
- vptr3->normal.z += polylist[totalpoly].normal.z;
- vptr3->connected++;
-
- /* Calculate center of polygon */
- min_depth = vptr->local.x;
- if (vptr2->local.x < min_depth)
- min_depth = vptr2->local.x;
- if (vptr3->local.x < min_depth)
- min_depth = vptr3->local.x;
- max_depth = vptr->local.x;
- if (vptr2->local.x > max_depth)
- max_depth = vptr2->local.x;
- if (vptr3->local.x > max_depth)
- max_depth = vptr3->local.x;
- polylist[totalpoly].center.x = (min_depth + max_depth) / 2.0;
-
- min_depth = vptr->local.y;
- if (vptr2->local.y < min_depth)
- min_depth = vptr2->local.y;
- if (vptr3->local.y < min_depth)
- min_depth = vptr3->local.y;
- max_depth = vptr->local.y;
- if (vptr2->local.y > max_depth)
- max_depth = vptr2->local.y;
- if (vptr3->local.y > max_depth)
- max_depth = vptr3->local.y;
- polylist[totalpoly].center.y = (min_depth + max_depth) / 2.0;
-
- min_depth = vptr->local.z;
- if (vptr2->local.z < min_depth)
- min_depth = vptr2->local.z;
- if (vptr3->local.z < min_depth)
- min_depth = vptr3->local.z;
- max_depth = vptr->local.z;
- if (vptr2->local.z > max_depth)
- max_depth = vptr2->local.z;
- if (vptr3->local.z > max_depth)
- max_depth = vptr3->local.z;
- polylist[totalpoly].center.z = (min_depth + max_depth) / 2.0;
- totalpoly++;
- }
- objectlist[totalobjects].end_poly = totalpoly - 1;
- totalobjects++;
- fseek (in, nextobj, SEEK_SET);
- break;
- case 0x4160 : // Loading Matrix
- fread (&mat11, 4, 1, in);
- fread (&mat12, 4, 1, in);
- fread (&mat13, 4, 1, in);
- fread (&mat21, 4, 1, in);
- fread (&mat22, 4, 1, in);
- fread (&mat23, 4, 1, in);
- fread (&mat31, 4, 1, in);
- fread (&mat32, 4, 1, in);
- fread (&mat33, 4, 1, in);
- fread (&mat41, 4, 1, in);
- fread (&mat42, 4, 1, in);
- fread (&mat43, 4, 1, in);
- break;
- case 0x4600 : // Light
- fread (&lightx, 4, 1, in);
- fread (&lighty, 4, 1, in);
- fread (&lightz, 4, 1, in);
- light_x = lightx;
- light_y = lighty;
- light_z = lightz;
- break;
- case 0x4700 : // Camera
- fread (&camx, 4, 1, in);
- fread (&camy, 4, 1, in);
- fread (&camz, 4, 1, in);
- camera_x = camx;
- camera_y = camy;
- camera_z = camz;
- fread (&tarx, 4, 1, in);
- fread (&tary, 4, 1, in);
- fread (&tarz, 4, 1, in);
- focus_x = tarx;
- focus_y = tary;
- focus_z = tarz;
- fread (&bank, 4, 1, in);
- camera_angle = bank;
- fread (&lens, 4, 1, in);
- fov = cameras[0].fov;
- for (i = 1; i < 9; i++)
- if (cameras[i].lens < lens)
- fov = cameras[i].fov;
- break;
- case 0xb000 : // Keyframer data
- break;
- case 0xb002 : // Object framedata
- break;
- case 0xb010 : // Found object
- nextobj = ftell (in) + chunk.next_chunk - 6;
-
- c = 0; /* Read the name */
- do {
- objname[c] = fgetc (in);
- c++;
- } while (objname[c-1] != 0);
-
- hiernum = find_object (objname);
-
- if (hiernum == -1) /* Dummy object */
- hiernum = OBJBUF - 1;
-
- fread (buffer, 4, 1, in);
- fread (&level, 2, 1, in);
-
- if (level == -1)
- {
- prevobj = hiernum;
- objectlist[hiernum].parent = -1;
- objectlist[hiernum].level = -1;
- }
- else if (level > objectlist[prevobj].level)
- {
- add_child(prevobj, hiernum);
- prevobj = hiernum;
- }
- else /* Need to back up the tree */
- {
- while ((level <= objectlist[prevobj].level) &&
- (objectlist[prevobj].level > -1))
- prevobj = objectlist[prevobj].parent;
- add_child (prevobj, hiernum);
- }
-
- for (i = 0; i < MAXKEYS; i++)
- objectlist[hiernum].keylist[i].framenumber = -1;
-
- objectlist[hiernum].maxframe = -1;
- fseek (in, nextobj, SEEK_SET);
- break;
-
- case 0xb020 : // Translation key
- nextobj = ftell (in) + chunk.next_chunk - 6;
- fread (buffer, 10, 1, in);
- fread (&numkeys, 4, 1, in);
-
- for (i = 0; i < numkeys; i++)
- {
- fread (&framenumber, 2, 1, in);
- fread (&buffer, 4, 1, in);
-
- fread (&x, 4, 1, in);
- fread (&y, 4, 1, in);
- fread (&z, 4, 1, in);
-
- add_key_translate (&objectlist[hiernum],
- framenumber, x, y, z);
- }
-
- fseek (in, nextobj, SEEK_SET);
- break;
-
-
- case 0xb021 : // Rotation key
- nextobj = ftell (in) + chunk.next_chunk - 6;
- fread (buffer, 10, 1, in);
- fread (&numkeys, 4, 1, in);
-
- for (i = 0; i < numkeys; i++)
- {
- fread (&framenumber, 2, 1, in);
- fread (buffer, 4, 1, in);
-
- fread (&rangle, 4, 1, in);
- fread (&rx, 4, 1, in);
- fread (&ry, 4, 1, in);
- fread (&rz, 4, 1, in);
- rangle = rangle * 180.0 / 3.1415;
-
- add_key_rotate (&objectlist[hiernum], framenumber,
- rx * rangle, ry * rangle, rz * rangle);
- }
-
- fseek (in, nextobj, SEEK_SET);
- break;
- case 0xb022 : // Scale key
- nextobj = ftell (in) + chunk.next_chunk - 6;
- fread (buffer, 10, 1, in);
- fread (&numkeys, 4, 1, in);
-
- for (i = 0; i < numkeys; i++)
- {
- fread (&framenumber, 2, 1, in);
- fread (buffer, 4, 1, in);
-
- fread (&rx, 4, 1, in);
- fread (&ry, 4, 1, in);
- fread (&rz, 4, 1, in);
-
- add_key_scale (&objectlist[hiernum],
- framenumber, rx, ry, rz);
- }
-
- fseek (in, nextobj, SEEK_SET);
- break;
-
- default : fseek (in, chunk.next_chunk-6, SEEK_CUR);
- }
- if (chunk.chunk_id == 0xb001)
- break;
-
- }
- else printf ("Not a 3DS file. Invalid header.\n");
- worldpoints = vertcnt;
- for (i = 0; i < worldpoints; i++)
- {
- pts[i].normal.x /= (float)pts[i].connected;
- pts[i].normal.y /= (float)pts[i].connected;
- pts[i].normal.z /= (float)pts[i].connected;
- }
- fclose (in);
- if ((camera_x == focus_x) && (camera_y == focus_y) && (camera_z == focus_z))
- {
- printf ("No camera loaded. Default view position set.\n");
- camera_x = -400;
- camera_y = -400;
- camera_z = -400;
- }
-
- build_hierarchy (); /* Not complete yet */
-
- l3dsstop:;
- if (libf != NULL)
- fclose (libf);
- }
-
-
- int compare (sort *a, sort *b)
- /* Used for sorting */
- {
- float comp;
-
- comp = a->depth - b->depth;
-
- //if (abs(comp) < 0.0005)
- //return 0;
- if (comp < 0)
- return 1;
- else return -1;
- }
-
-
- void draw_polys (vertex *pts, int drawtotal)
- /* Draw all of the polygons in order, using our rendering method */
- {
- char shade;
- int d, e;
- int first;
- float dotprod;
- triangle_3d *ptr;
- vertex *vptr;
- vertex *vptr2;
- vertex *vptr3;
- sort tempsort;
- point3d *lightnorm;
- float lnormx, lnormy, lnormz;
- int polynum;
-
- lightnorm = &light.normal;
-
- for (d = 0; d < worldpoints; d++)
- pts[d].rotated = 0;
-
- qsort (sorted_polys, drawtotal, sizeof (sort), compare);
-
- lnormx = lightnorm->x;
- lnormy = lightnorm->y;
- lnormz = lightnorm->z;
-
- first = drawtotal - 1;
- for (d = 0; d <= first; d++)
- {
- polynum = sorted_polys[d].number;
-
- ptr = &polylist[polynum];
- vptr = &pts[ptr->vertex1];
- vptr2 = &pts[ptr->vertex2];
- vptr3 = &pts[ptr->vertex3];
-
- renderpoly[0].x = vptr->screenx;
- renderpoly[0].y = vptr->screeny;
- renderpoly[1].x = vptr2->screenx;
- renderpoly[1].y = vptr2->screeny;
- renderpoly[2].x = vptr3->screenx;
- renderpoly[2].y = vptr3->screeny;
-
- vptr->rotated = 0;
- vptr2->rotated = 0;
- vptr3->rotated = 0;
-
- if (ptr->type == WIREFRAME)
- {
- wsetcolor (ptr->color);
- if (ptr->status & 4)
- wline (renderpoly[0].x, renderpoly[0].y, renderpoly[1].x, renderpoly[1].y);
- if (ptr->status & 2)
- wline (renderpoly[1].x, renderpoly[1].y, renderpoly[2].x, renderpoly[2].y);
- if (ptr->status & 1)
- wline (renderpoly[2].x, renderpoly[2].y, renderpoly[0].x, renderpoly[0].y);
- }
- else if (ptr->type == SOLID)
- {
- dotprod = (ptr->normal.x * lnormx) + (ptr->normal.y * lnormy) +
- (ptr->normal.z * lnormz);
-
- if (dotprod < 0)
- renderpoly[0].col = dotprod * render_shades;
- else renderpoly[0].col = 0;
-
- wsetcolor (ptr->color - renderpoly[0].col);
- wtriangle_solid (renderpoly);
- }
- else if (ptr->type == GOURAUD)
- {
- dotprod = (vptr->normal.x * lnormx) + (vptr->normal.y * lnormy) +
- (vptr->normal.z * lnormz);
- if (dotprod > 0)
- dotprod = 0;
- renderpoly[0].col = ptr->color - dotprod * render_shades;
-
- dotprod = (vptr2->normal.x * lnormx) + (vptr2->normal.y * lnormy) +
- (vptr2->normal.z * lnormz);
- if (dotprod > 0)
- dotprod = 0;
- renderpoly[1].col = ptr->color - dotprod * render_shades;
-
- dotprod = (vptr3->normal.x * lnormx) + (vptr3->normal.y * lnormy) +
- (vptr3->normal.z * lnormz);
- if (dotprod > 0)
- dotprod = 0;
- renderpoly[2].col = ptr->color - dotprod * render_shades;
-
- wtriangle_gouraud (renderpoly);
- }
- else if (ptr->type == TEXTURE)
- {
- renderpoly[0].sx = ptext[polynum].sx[0];
- renderpoly[0].sy = ptext[polynum].sy[0];
- renderpoly[1].sx = ptext[polynum].sx[1];
- renderpoly[1].sy = ptext[polynum].sy[1];
- renderpoly[2].sx = ptext[polynum].sx[2];
- renderpoly[2].sy = ptext[polynum].sy[2];
-
- wtriangle_texture (renderpoly, textures[ptr->color]);
- }
- else if (ptr->type == FLAT_SHADED_TEXTURE)
- {
- dotprod = (ptr->normal.x * lnormx) + (ptr->normal.y * lnormy) +
- (ptr->normal.z * lnormz);
- if (dotprod < 0)
- shade = -dotprod * render_shades;
- else shade = 0;
-
- renderpoly[0].sx = ptext[polynum].sx[0];
- renderpoly[0].sy = ptext[polynum].sy[0];
- renderpoly[1].sx = ptext[polynum].sx[1];
- renderpoly[1].sy = ptext[polynum].sy[1];
- renderpoly[2].sx = ptext[polynum].sx[2];
- renderpoly[2].sy = ptext[polynum].sy[2];
-
- wtriangle_flat_shaded_texture (renderpoly, textures[ptr->color],
- shade, render_shadetable);
- }
- else if (ptr->type == GOURAUD_SHADED_TEXTURE)
- {
- dotprod = (vptr->normal.x * lnormx) + (vptr->normal.y * lnormy) +
- (vptr->normal.z * lnormz);
- if (dotprod > 0)
- dotprod = 0;
- renderpoly[0].col = -dotprod * render_shades;
-
- dotprod = (vptr2->normal.x * lnormx) + (vptr2->normal.y * lnormy) +
- (vptr2->normal.z * lnormz);
- if (dotprod > 0)
- dotprod = 0;
- renderpoly[1].col = -dotprod * render_shades;
-
- dotprod = (vptr3->normal.x * lnormx) + (vptr3->normal.y * lnormy) +
- (vptr3->normal.z * lnormz);
- if (dotprod > 0)
- dotprod = 0;
- renderpoly[2].col = -dotprod * render_shades;
-
- renderpoly[0].sx = ptext[polynum].sx[0];
- renderpoly[0].sy = ptext[polynum].sy[0];
- renderpoly[1].sx = ptext[polynum].sx[1];
- renderpoly[1].sy = ptext[polynum].sy[1];
- renderpoly[2].sx = ptext[polynum].sx[2];
- renderpoly[2].sy = ptext[polynum].sy[2];
-
- wtriangle_gouraud_shaded_texture (renderpoly, textures[ptr->color],
- render_shadetable);
- }
- else if (ptr->type == TRANSLUCENT_TEXTURE)
- {
- renderpoly[0].sx = ptext[polynum].sx[0];
- renderpoly[0].sy = ptext[polynum].sy[0];
- renderpoly[1].sx = ptext[polynum].sx[1];
- renderpoly[1].sy = ptext[polynum].sy[1];
- renderpoly[2].sx = ptext[polynum].sx[2];
- renderpoly[2].sy = ptext[polynum].sy[2];
-
- wtriangle_translucent_texture (renderpoly, textures[ptr->color],
- render_shadetable);
- }
- else if (ptr->type == TRANSLUCENT_GOURAUD)
- {
- dotprod = (vptr->normal.x * lnormx) + (vptr->normal.y * lnormy) +
- (vptr->normal.z * lnormz);
- if (dotprod > 0)
- dotprod = 0;
- renderpoly[0].col = ptr->color - dotprod * render_shades;
-
- dotprod = (vptr2->normal.x * lnormx) + (vptr2->normal.y * lnormy) +
- (vptr2->normal.z * lnormz);
- if (dotprod > 0)
- dotprod = 0;
- renderpoly[1].col = ptr->color - dotprod * render_shades;
-
- dotprod = (vptr3->normal.x * lnormx) + (vptr3->normal.y * lnormy) +
- (vptr3->normal.z * lnormz);
- if (dotprod > 0)
- dotprod = 0;
- renderpoly[2].col = ptr->color - dotprod * render_shades;
-
- wtriangle_translucent_gouraud (renderpoly, render_shadetable);
- }
-
- }
- }
-
-
-
-
- void map_plane (float x, float y, float z, long *u, long *v, float scale)
- /* Given a 3D point, maps the point onto the x/y plane */
- {
- *u = x * scale;
- *v = y * scale;
- }
-
-
-
- void wset_object_color (int obj, unsigned char col)
- /* Sets the color of each triangle in an object, used for solid, gouraud, and
- texture. For textured objects, the color represents the texture number
- from the textures array. */
- {
- int poly;
- object_3d *objp;
-
- objp = &objectlist[obj];
-
- for (poly = objp->start_poly; poly <= objp->end_poly; poly++)
- polylist[poly].color = col;
-
- }
-
-
- void wset_object_type (int obj, int type)
- /* Sets the rendering method for an object */
- {
- int poly;
- object_3d *objp;
-
- objp = &objectlist[obj];
-
- for (poly = objp->start_poly; poly <= objp->end_poly; poly++)
- polylist[poly].type = type;
-
- }
-
-
- void wreset_3d_system (void)
- /* Resets the engine so you can load in a new object */
- {
- totalpoly = 0;
- totalobjects = 0;
- }
-
-
-